import { useStore, mapState,mapGetters,mapMutations,mapActions } from 'vuex'
import { computed } from 'vue'

//mapper： Array | Object
/* export const useState = function(mapper,namespace?:string):object {
    const store = useStore()
    
    //使用复制函数解析成一个对象
    const storeStateObj = namespace? mapState(namespace,mapper):mapState(mapper)
    const res = {}
    
    //通过Object.keys拿到对象的所有key值，遍历，取出对应的value值，也就是函数
    Object.keys(storeStateObj).forEach(item => {
        //这我们知道辅助函数的内部是通过this.$store来实现的
        //setup中没有this， 所以通过bind来改变this的指向
        const fn = storeStateObj[item].bind({$store:store})
        //拿到函数，作为计算属性的参数，最后在留在一个对象中
        res[item] = computed(fn)
    })
    
    //res是一个对象， key是字符串， value值是ref对象
    return res
} */

/**
 *
 * @param mapperFn 传入的map辅助函数，mapState, mapGetters, mapActions, mapMutations
 * @param mapper 方法或者属性的名字，actions或者mutations或者getter的函数名，state的属性名字
 * @param module  开启命名空间后的模块名
 * @returns {{}} 返回数组，数组内容为fn函数，fn函数为每个属性所对应的map辅助函数
 */
const hooks = (mapperFn, mapper, module) => {
  const store = useStore();  // 引入vuex中的useStore函数
  const resultFn = {};
  let mapData = {};
  if (module) {  // 判断是否存在命名空间，如果存在则绑定
    mapData = mapperFn(module, mapper);
  } else {
    mapData = mapperFn(mapper);
  }
  Object.keys(mapData).forEach( item => {
    const fn = mapData[item].bind({'$store': store});  // 使用bind方法将得到map函数结果绑定到vuex上
    resultFn[item] = fn;
  });
  return resultFn
}

/**
 * 满足mapState和mapGetters调用
 * @param mapperFn 传入的map辅助函数，主要是mapState和mapGetters
 * @param mapper  数组类型，主要是变量或者返回值的key
 * @param module   打开命名空间，模块名称，非必传
 * 调用hooks函数后得到其返回值，然后将返回值放在computed中做一个监听，
 * computed参会可以是函数的返回值，即这样就完成了对数据的返回监听
 */
const useDataHooks = (mapperFn, mapper, module) => {
  let hooksData = hooks( mapperFn, mapper, module);
  const resultFn = {};
  const result = {};
  Object.keys(hooksData).forEach( item => {
    resultFn[item] = computed(hooksData[item]);
    result[item] = resultFn[item].value
  });
  return result
}

/**
 * 封装useState函数
 * @param module   命名空间，名称
 * @param mapper  数组， state中定义的变量名称
 */
export const useState = (mapper, module) => {
  return useDataHooks(mapState, mapper, module)
}

/**
 * 封装useGetters函数
 * @param module  命名空间，
 * @param mapper 数组，即getters中的返回值名称
 */
export const useGetters = (mapper, module) => {
  return useDataHooks(mapGetters, mapper, module)
}

/**
 * 封装mapMutations函数
 * @param mapper  数组，mutations中函数的名称
 * @param module  命名空间，模块名称
 */
export const useMutations = (mapper, module) => {
  return hooks( mapMutations , mapper, module);
}
/**
 * 封装mapActions函数
 * @param mapper  数组，actions中函数的名称
 * @param module  命名空间，模块名称
 */
export const useActions = (mapper, module) => {
  return hooks( mapActions , mapper, module);
}